// Linux信号-信号保存，对三个信号表进行操作 -20230107-
#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <assert.h>

using namespace std;

void handler(int sig)
{
    cout << "捕捉了当前" << sig << "信号" << endl;
}

// 给对应信号添加信号屏蔽字
void AddBlock(int sig)
{
    sigset_t bset;
    // 信号集先初始化为0
    int n = sigemptyset(&bset);
    assert(n == 0);
    (void)n;
    sigaddset(&bset, sig);  // 对应信号进行添加进行添加

    n = sigprocmask(SIG_BLOCK, &bset, nullptr);  // 第三个参数是原来的信号集，这里是封装的函数，可以不需要哦
    assert(n == 0);
}
// 给对应信号去除信号屏蔽字
void EraseBlock(int sig)
{
    sigset_t bset;
    int n = sigemptyset(&bset);
    assert(n == 0);
    (void)n;
    sigaddset(&bset, sig);  // 对应信号进行添加进行添加

    n = sigprocmask(SIG_UNBLOCK, &bset, nullptr);  //只是操作方法变了 SIG_UNBLOCK -> &(~)
    assert(n == 0);
}

// 打印当前进程的pengding信号集
void PrintPengding()
{
    sigset_t pset;  // 使用接口的是赋值，所以不需要进行初始化
    int n = sigpending(&pset);
    assert(n == 0);
    (void)n;

    for (int i = 1; i <= 31; ++i)
    {
        if (sigismember(&pset, i)) cout << "1";
        else cout << "0";
    }
    cout << endl;
}

int main()
{
    // 3 将1 ~31信号全部屏蔽，打印pengding表观察现象
    for (int i = 1; i <= 31; ++i) AddBlock(i);
    while (true)
    {
        PrintPengding();
        sleep(1);
    }

    // 2 设置对应信号的屏蔽字 解除 打印当前进pengding信号集
    // 我们可以先对2号信号进行一个捕捉
    // signal(2, handler);
    // // 对2号信号设置屏蔽字
    // AddBlock(2);
    // cout << "2号信号已经屏蔽" << endl;
    // int count = 0;
    // while (true)
    // {
    //     count++;
    //     if (count == 20)
    //     {
    //         // 当加到20的时候，我们将2号信号的信号屏蔽字进行解除，观察pengding表的变化
    //         cout << "2号信号屏蔽解除" << endl;
    //         EraseBlock(2);
    //     }
    //     PrintPengding();  // 不断的打印
    //     sleep(1);
    // }

    // 1 自定义捕捉1 ~ 31 是不是此时此进程就无敌了呢？
    // for (int i = 0; i <= 31; ++i)
    // {
    //     signal(i, handler);
    // }
    // while (true) sleep(1);  // 循环验证

    return 0;
}